﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SpaceshipDuel
{
    /// <summary>
    /// Zustand für Türme
    /// </summary>
    public enum TurretState
    {
        closed,
        opening,
        open,
        closing
    }

    /// <summary>
    /// Gegner: Turm - stationär, beschießt Spieler bei Annäherung
    /// </summary>
    public class Turret : GameObject
    {
        #region Private fields

        int structIntegrity;            // Lebenspunkte
        bool destroyMe;                 // Flag zum Löschen
        WaitTimer animTimer;            // Timer für Öffnen- und Schließen-Animation
        int frameCount;                 // zählt die Animationsframes
        TurretState state;              // Zustand
        Vector2 target;                 // Koordinaten für das Ziel, das beschossen werden soll
        TextureData shotTextureData;    // Geschoss-Textur
        WaitTimer nextBulletTimer;      // Timer für Schussfrequenz
        float bulletSpeed;              // Geschwindigkeit der Schüsse
        int maxBulletDistance;          // Flugweite der Schüsse
        List<Bullet> bullets;           // Refernz auf Geschossliste

        #endregion Private fields

        #region Public properties

        public bool DestroyMe
        {
            get { return this.destroyMe; }
            set { this.destroyMe = value; }
        }

        public int Radius
        {
            get 
            {
                if (this.state == TurretState.closed || this.state == TurretState.closing)
                    return 19;  // Radius wenn geschlossen
                else
                    return 24;  // Radius wenn offen
            }
        }

        public TurretState State
        {
            get { return this.state; }
            set 
            {
                animTimer.Reset();
                this.state = value; 
            }
        }

        #endregion Public properties

        #region Construction

        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="newTextureData"></param>
        /// <param name="newShotTextureData"></param>
        /// <param name="newCenter"></param>
        /// <param name="newWorldSize"></param>
        /// <param name="newBullets"></param>
        public Turret(TextureData newTextureData, TextureData newShotTextureData, Vector2 newCenter, int newWorldSize, ref List<Bullet> newBullets)
        {
            destroyMe = false;
            textureData = newTextureData;
            center = newCenter;
            worldSize = newWorldSize;
            structIntegrity = 40;
            animTimer = new WaitTimer(0.01f);
            frameCount = 0;
            state = TurretState.closed;
            target = new Vector2();
            shotTextureData = newShotTextureData;
            bullets = newBullets;
            bulletSpeed = 7.0f;
            maxBulletDistance = 2000;
            nextBulletTimer = new WaitTimer(0.15f);
        }

        #endregion Construction

        #region Public methods

        /// <summary>
        /// Update-Methode
        /// </summary>
        public void Update(GameTime gameTime)
        {
            if (destroyMe == false)
            {
                if (structIntegrity <= 0)
                    destroyMe = true;

                 if (animTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds) == true)
                 {
                     // Turm öffnen
                     if (state == TurretState.opening)
                     {
                        frameCount++;
                        if (frameCount == 9)
                            state = TurretState.open;
                     }

                     // Turm schließen
                     if (state == TurretState.closing)
                     {
                         frameCount--;
                         if (frameCount == 0)
                             state = TurretState.closed;
                     }
                 }

                 // Turm geöffnet -> schießen
                 if (state == TurretState.open)
                     if (nextBulletTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds) == true)
                        Shoot(gameTime);   
            }
        }

        /// <summary>
        /// Draw-Methode
        /// </summary>
        /// <param name="spriteBatch">Spritebacth</param>
        /// <param name="xOffset">Offset X</param>
        /// <param name="yOffset">Offset Y</param>
        new public void Draw(SpriteBatch spriteBatch, float xOffset, float yOffset)
        {
            if (destroyMe == false)
            {
                Vector2 position = new Vector2(center.X + xOffset, center.Y + yOffset);
                Vector2 origin = new Vector2(textureData.tileWidth / 2, textureData.tileHeight / 2);
                Rectangle sourceRect = new Rectangle(frameCount % textureData.tileCountX * textureData.tileWidth, frameCount / textureData.tileCountX * textureData.tileHeight, textureData.tileWidth, textureData.tileHeight);
                spriteBatch.Draw(textureData.texture, position, sourceRect, Color.White, 0, origin, 1.0f, SpriteEffects.None, 0f);
            }
        }

        // Treffer
        public void Hit(int damage = 1)
        {
            structIntegrity -= damage;
        }

        /// <summary>
        /// Setzen eines Ziels
        /// </summary>
        /// <param name="targetCenter">Koordinaten des Ziels</param>
        public void SetTarget(Vector2 targetCenter)
        {
            target = targetCenter;
        }

        #endregion Public methods

        #region Private methods

        /// <summary>
        /// Shooting single shots
        /// </summary>
        /// <param name="gameTime"></param>
        private void Shoot(GameTime gameTime)
        {
            // Erzeuge virtuelle Koordinaten zur Zielerfassung, falls Ziel und Turm in verschiedenen
            // Quadranten des Spielfeldes liegen...
            Vector2 newTarget = target;
            Vector2 newCenter = center;

            float resultX = (float)Math.Abs(target.X - center.X);
            if (resultX > worldSize / 2)
            {
                newTarget.X = (target.X + worldSize / 2) % worldSize;
                newCenter.X = (center.X + worldSize / 2) % worldSize;
            }

            float resultY = (float)Math.Abs(target.Y - center.Y);
            if (resultY > worldSize / 2)
            {
                newTarget.Y = (target.Y + worldSize / 2) % worldSize;
                newCenter.Y = (center.Y + worldSize / 2) % worldSize;
            }

            float rotationAngle = (float)(Math.Atan2(newTarget.Y - newCenter.Y, newTarget.X - newCenter.X) + Math.PI / 2);

            Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
            bulletDirection.Normalize();

            Vector2 bulletPosition = new Vector2(center.X, center.Y) + bulletDirection * 32;
            Bullet bullet = new Bullet(shotTextureData, bulletPosition, this.worldSize, bulletSpeed, rotationAngle, bulletDirection, maxBulletDistance, 2);

            bullets.Add(bullet);
            nextBulletTimer.Reset();
        }

        #endregion Private methods
    }
}
